package com.hog.web.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hog.dto.TextMessage;
import com.hog.enums.DltRuleEnum;
import com.hog.enums.SsqRuleEnum;
import com.hog.service.article.IBlogArticleWebService;
import com.hog.utils.Base64Util;
import com.hog.utils.HttpClientUtils;
import com.hog.utils.ListUtil;
import com.hog.utils.SignUtil;
import com.hog.utils.StringUtils;
import com.hog.utils.WechatMessageUtil;
import com.hog.utils.date.DateStyle;
import com.hog.utils.date.DateUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 后台主页控制器
 *
 * @author 糖先森
 * @date 2018年03月21日
 * @since JDK 1.8
 */
@Controller
@RequestMapping("/")
@Slf4j
public class IndexController {
    @Autowired
    private IBlogArticleWebService articleWebService;

    @RequestMapping(value = "", method = RequestMethod.GET)
    public String index(Model model) {
        model.addAttribute("newestArticleList", articleWebService.newestArticleList());
        model.addAttribute("randomList", articleWebService.randomRecommendation());
        model.addAttribute("sharingList", articleWebService.getSharingList());
        return "blog_index";
    }

    @RequestMapping(value = "info", method = RequestMethod.GET)
    public String info() {
        return "info";
    }

    @RequestMapping(value = "prompt", method = RequestMethod.GET)
    public String prompt() {
        return "prompt";
    }

    /**
     * 分页(list-web-2)
     *
     * @return
     */
    @RequestMapping(value = "list-{type}-{index}", method = RequestMethod.GET)
    public String list(@PathVariable("type") String type, @PathVariable("index") Integer index, Model model) {
        log.info("进入分页: {}, {}", type, index);
        model.addAttribute("articleList", articleWebService.list(index));
        model.addAttribute("pageInfo", articleWebService.getPageInfo(index));
        model.addAttribute("sharingList", articleWebService.getSharingList());
        model.addAttribute("type", type);
        return "blog_list";
    }

    /**
     * 分页(time/list-web-20200825-1)
     *
     * @return
     */
    @RequestMapping(value = "time/list-{type}-{date}-{index}", method = RequestMethod.GET)
    public String timeList(@PathVariable("type") String type, @PathVariable("date") String date, @PathVariable("index") Integer index, Model model) {
        log.info("进入日期分页: {}, {}", type, index);
        model.addAttribute("articleList", articleWebService.timeList(date, index));
        model.addAttribute("pageInfo", articleWebService.getPageInfoByTime(date, index));
        model.addAttribute("sharingList", articleWebService.getSharingList());
        model.addAttribute("date", date);
        model.addAttribute("dateFmt", DateUtils.DateToString(DateUtils.StringToDate(date, DateStyle.YYYYMMDD), DateStyle.YYYY年MM月DD日));
        return "blog_list_time";
    }

    /**
     * 获取大乐透中奖信息
     *
     * @return
     */
    @RequestMapping(value = "dlt", method = RequestMethod.GET)
    @ResponseBody
    public JSONObject dlt(String number) throws Exception {
        PrizeResultDTO dltPrize = getDltPrize(number);
        PrizeResultDTO ssqPrize = getSsqPrize(number);
        Map<String, PrizeResultDTO> resultMap = new HashMap<>();
        resultMap.put("大乐透", dltPrize);
        resultMap.put("双色球", ssqPrize);
        return JSONObject.parseObject(JSONObject.toJSONString(resultMap));
    }

    /**
     * 微信token认证
     *
     * @param response
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @throws Exception
     */
    @RequestMapping(value = "wechat", method = RequestMethod.GET)
    @ResponseBody
    public void wechat(HttpServletResponse response,
                       @RequestParam(value = "signature", required = false) String signature,
                       @RequestParam(value = "timestamp", required = false) String timestamp,
                       @RequestParam(value = "nonce", required = false) String nonce,
                       @RequestParam(value = "echostr", required = false) String echostr) throws Exception {
        System.out.println("收到微信消息: ");
        System.out.println("signature: " + signature);
        System.out.println("timestamp: " + timestamp);
        System.out.println("nonce: " + nonce);
        System.out.println("echostr: " + echostr);

        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        PrintWriter out = response.getWriter();

        if (StringUtils.isNotBlank(signature)) {
            log.info("signature[{}], timestamp[{}], nonce[{}], echostr[{}]", signature, timestamp, nonce, echostr);
            if (SignUtil.checkSignature(signature, timestamp, nonce)) {
                log.info("数据源为微信后台，将echostr[{}]返回！", echostr);
                out.print(echostr);
                out.flush();
            }
        }
    }

    /**
     * 接收微信消息
     *
     * @param request
     * @param response
     */
    @ResponseBody
    @RequestMapping(value = "/wechat", method = RequestMethod.POST)
    public void wechatServicePost(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("收到微信消息");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        PrintWriter out = response.getWriter();
        try {
            List<String> imgNumList = new ArrayList<>();
            TextMessage textMessage = processRequest(request, imgNumList);

            if (ListUtil.isEmpty(imgNumList)) {
                String content = textMessage.getContent();

                PrizeResultDTO dltPrize = getDltPrize(content);
                PrizeResultDTO ssqPrize = getSsqPrize(content);
                Map<String, PrizeResultDTO> resultMap = new HashMap<>();
                resultMap.put("大乐透", dltPrize);
                resultMap.put("双色球", ssqPrize);

                String resultMsg = "超级大乐透: \n" +
                        "期数: " + dltPrize.getPeriods() + "\n" +
                        "奖池金额: " + dltPrize.getLotteryPoolAmount() + "\n" +
                        "开奖日期: " + dltPrize.getOpenDate() + "\n" +
                        "中奖号码: " + dltPrize.getLotteryRes() + "\n" +
                        "中奖前后区: " + dltPrize.getMyPrize() + "\n" +
                        "中奖结果: " + dltPrize.getPrize() + "\n" +
                        "中奖奖金: " + dltPrize.getPrizeAmount() +
                        "\n\n" +
                        "双色球: \n" +
                        "期数: " + ssqPrize.getPeriods() + "\n" +
                        "奖池金额: " + ssqPrize.getLotteryPoolAmount() + "\n" +
                        "开奖日期: " + ssqPrize.getOpenDate() + "\n" +
                        "中奖号码: " + ssqPrize.getLotteryRes() + "\n" +
                        "中奖前后区: " + ssqPrize.getMyPrize() + "\n" +
                        "中奖结果: " + ssqPrize.getPrize() + "\n" +
                        "中奖奖金: " + ssqPrize.getPrizeAmount();
                textMessage.setContent(resultMsg);
                String responseMessage = handleResponseMessage(textMessage);
                out.print(responseMessage);
                out.flush();
            } else {
                StringBuilder sb = new StringBuilder();

                for (String num : imgNumList) {
                    if (num.length() == 15) {
                        log.info("识别大乐透: {}", num);
                        // 大乐透
                        List<String> dltList = new ArrayList<>();
                        dltList.add(num.substring(0, 2));
                        dltList.add(num.substring(2, 4));
                        dltList.add(num.substring(4, 6));
                        dltList.add(num.substring(6, 8));
                        dltList.add(num.substring(8, 10));
                        dltList.add(num.substring(11, 13));
                        dltList.add(num.substring(13, 15));
                        String content = StringUtils.join(dltList, ",");
                        log.info("识别大乐透: {}", content);
                        PrizeResultDTO dltPrize = getDltPrize(content);
                        Map<String, PrizeResultDTO> resultMap = new HashMap<>();
                        resultMap.put("大乐透", dltPrize);

                        if (StringUtils.isEmpty(sb.toString())) {
                            sb.append("超级大乐透");
                            sb.append("期数: " + dltPrize.getPeriods() + "\n" +
                                    "奖池金额: " + dltPrize.getLotteryPoolAmount() + "\n" +
                                    "开奖日期: " + dltPrize.getOpenDate() + "\n" +
                                    "中奖号码: " + dltPrize.getLotteryRes() + "\n\n");
                        }

                        String resultMsg = content + ": \n" +
                                "中奖前后区: " + dltPrize.getMyPrize() + "\n" +
                                "中奖结果: " + dltPrize.getPrize() + "\n" +
                                "中奖奖金: " + dltPrize.getPrizeAmount() +
                                "\n\n";
                        sb.append(resultMsg);
                    } else if (num.length() == 17) {
                        log.info("识别双色球: {}", num);
                        // 双色球
                        List<String> ssqList = new ArrayList<>();

                        ssqList.add(num.substring(0, 2));
                        ssqList.add(num.substring(2, 4));
                        ssqList.add(num.substring(4, 6));
                        ssqList.add(num.substring(6, 8));
                        ssqList.add(num.substring(8, 10));
                        ssqList.add(num.substring(10, 12));
                        ssqList.add(num.substring(15, 17));
                        String content = StringUtils.join(ssqList, ",");
                        log.info("识别双色球: {}", content);

                        PrizeResultDTO ssqPrize = getSsqPrize(content);
                        Map<String, PrizeResultDTO> resultMap = new HashMap<>();
                        resultMap.put("双色球", ssqPrize);

                        if (StringUtils.isEmpty(sb.toString())) {
                            sb.append("双色球");
                            sb.append("期数: " + ssqPrize.getPeriods() + "\n" +
                                    "奖池金额: " + ssqPrize.getLotteryPoolAmount() + "\n" +
                                    "开奖日期: " + ssqPrize.getOpenDate() + "\n" +
                                    "中奖号码: " + ssqPrize.getLotteryRes() + "\n\n");
                        }

                        String resultMsg = content + ": \n" +
                                "中奖前后区: " + ssqPrize.getMyPrize() + "\n" +
                                "中奖结果: " + ssqPrize.getPrize() + "\n" +
                                "中奖奖金: " + ssqPrize.getPrizeAmount() + "\n\n";
                        sb.append(resultMsg);
                    } else {
                        log.info("图片识别失败, 请按要求截图!");
                        sb.append("图片识别失败, 请按要求截图, 识别结果: " + JSONArray.toJSONString(imgNumList));
                        break;
                    }
                }

                textMessage.setContent(sb.toString());
                String responseMessage = handleResponseMessage(textMessage);
                out.print(responseMessage);
                out.flush();
            }
        } catch (Exception e) {
            out.print("系统异常: " + e.getMessage());
            out.flush();
        }
    }

    public TextMessage processRequest(HttpServletRequest request, List<String> imgNumList) throws IOException {
        Map<String, String> map = WechatMessageUtil.xmlToMap(request);
        log.info(JSONObject.toJSONString(map));
        // 发送方帐号（一个OpenID）
        String fromUserName = map.get("FromUserName");
        // 开发者微信号
        String toUserName = map.get("ToUserName");
        // 消息类型
        String msgType = map.get("MsgType");
        // 消息类型
        String content = map.get("Content");
        log.info("消息内容: {}", content);

        // 对消息进行处理
        // 文本消息
        if (WechatMessageUtil.MESSAGE_TEXT.equals(msgType)) {
            TextMessage textMessage = new TextMessage();
            textMessage.setMsgType(WechatMessageUtil.MESSAGE_TEXT);
            textMessage.setToUserName(fromUserName);
            textMessage.setFromUserName(toUserName);
            textMessage.setCreateTime(System.currentTimeMillis());
            textMessage.setContent(content);
            return textMessage;
        } else if (WechatMessageUtil.MESSAtGE_IMAGE.equals(msgType)) {
            String picUrl = map.get("PicUrl");
            log.info("识别图片: {}", picUrl);
            // 调用百度识图接口
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("image", Base64Util.image2Base64(picUrl));
            String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic?access_token=" + getAccessToken();
            String result = HttpClientUtils.httpPost(url, paramMap, HttpClientUtils.CHARSET_UTF8, new HashMap<>());
            log.info("百度识图结果: {}", result);
            JSONArray wordsResult = JSONObject.parseObject(result).getJSONArray("words_result");

            for (int i = 0; i < wordsResult.size(); i++) {
                JSONObject jsonObject = wordsResult.getJSONObject(i);
                String words = StringUtils.emptyIfNull(jsonObject.get("words"));
                imgNumList.add(words);
            }

            TextMessage textMessage = new TextMessage();
            textMessage.setMsgType(WechatMessageUtil.MESSAGE_TEXT);
            textMessage.setToUserName(fromUserName);
            textMessage.setFromUserName(toUserName);
            textMessage.setCreateTime(System.currentTimeMillis());
            textMessage.setContent(JSONArray.toJSONString(imgNumList));

            return textMessage;
        }

        return null;
    }

    private String getAccessToken() throws IOException {
        String url = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=MCWz44WOWbOMS79x2XXMZze5&client_secret=CpZiUgNbpXYCOx63xOfB6Il15oZYOqNB";
        String result = HttpClientUtils.httpPost(url, "", HttpClientUtils.CHARSET_UTF8);
        return StringUtils.emptyIfNull(JSONObject.parseObject(result).get("access_token"));
    }

    /**
     * 生成处理回复消息
     *
     * @param textMessage
     * @return
     */
    private String handleResponseMessage(TextMessage textMessage) {
        // 默认回复一个"success"
        String responseMessage = "success";
        responseMessage = WechatMessageUtil.textMessageToXml(textMessage);
        log.info(responseMessage);
        return responseMessage;
    }

    public static void main(String[] args) throws Exception {
        IndexController indexController = new IndexController();
        indexController.getAccessToken();

//        getDltPrize("7，8,23,26,32,9,12");
//
//        getSsqPrize("7,8,23,26,32,9,11");
//        Map<String, String> paramMap = new HashMap<>();
//        paramMap.put("url", "http://mmbiz.qpic.cn/mmbiz_jpg/xs13AfNRA9AuNRTqiasY8JgK1XfcLnmaLTN0IgmdkO0aUyaTX2EEicgxQFTNnSFemJ40ic0j2aDIjLFBpEYdlyZxQ/0");
//        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token=24.71a559380a5aecddadeced9ce2ae6546.2592000.1616837934.282335-10290702";
//        String result = HttpClientUtils.httpPost(url, paramMap, HttpClientUtils.CHARSET_UTF8, new HashMap<>());
//        log.info("百度识图结果: {}", result);

//        String str = "0304183335+1012";
//        System.out.println(str.length());
//        System.out.println(str.substring(0, 2));
//        System.out.println(str.substring(2, 4));
//        System.out.println(str.substring(4, 6));
//        System.out.println(str.substring(6, 8));
//        System.out.println(str.substring(8, 10));
//        System.out.println(str.substring(11, 13));
//        System.out.println(str.substring(13, 15));


//        String ssq = "020612273033-蓝区11";
//        System.out.println(ssq.substring(0, 2));
//        System.out.println(ssq.substring(0, 2));
//        System.out.println(ssq.substring(2, 4));
//        System.out.println(ssq.substring(4, 6));
//        System.out.println(ssq.substring(6, 8));
//        System.out.println(ssq.substring(8, 10));
//        System.out.println(ssq.substring(10, 12));
//        System.out.println(ssq.substring(15, 17));
//        System.out.println("020612273033-".length());

        List<String> strings = Arrays.asList("12", "11", "09");
        System.out.println(StringUtils.join(strings));
        System.out.println(StringUtils.join(strings, ","));
    }


    private static PrizeResultDTO getDltPrize(String number) throws Exception {
        // 解决中文逗号的问题
        number = number.replace("，", ",");
        // 获取最新结果
        PrizeResultDTO prizeResultDTO = new PrizeResultDTO();
        List<String> resultList = getDltResult(prizeResultDTO);
        // 客户端输入
        List<String> myList = new ArrayList<>(Arrays.asList(number.split(",")));

        if (myList.size() != 7) {
            throw new Exception("参数不合法!");
        }

        List<String> myFrontList = new ArrayList<>(myList.subList(0, 5));
        List<String> myAfterList = new ArrayList<>(myList.subList(5, 7));

        System.out.println("my前: " + JSONArray.toJSONString(myFrontList));
        System.out.println("my后: " + JSONArray.toJSONString(myAfterList));

        List<String> resultFrontList = new ArrayList<>(resultList.subList(0, 5));
        List<String> resultAfterList = new ArrayList<>(resultList.subList(5, 7));

        System.out.println("result前: " + JSONArray.toJSONString(resultFrontList));
        System.out.println("result后: " + JSONArray.toJSONString(resultAfterList));

        myFrontList.retainAll(resultFrontList);
        myAfterList.retainAll(resultAfterList);

        System.out.println(myFrontList.size() + ": " + JSONArray.toJSONString(myFrontList));
        System.out.println(myAfterList.size() + ": " + JSONArray.toJSONString(myAfterList));
        String rule = String.format("%s+%s", myFrontList.size(), myAfterList.size());

        prizeResultDTO.setLotteryRes(StringUtils.join(resultList, ","));
        prizeResultDTO.setPrize(rule);
        prizeResultDTO.setPrizeAmount(DltRuleEnum.getPrizeNameByRule(rule));
        prizeResultDTO.setMyPrize("前区: " + StringUtils.join(myFrontList, ",") + "后区: " + StringUtils.join(myAfterList, ","));
        log.info("prizeResultDTO: {}", JSONObject.toJSONString(prizeResultDTO));
        return prizeResultDTO;
    }

    private static PrizeResultDTO getSsqPrize(String number) throws Exception {
        // 解决中文逗号的问题
        number = number.replace("，", ",");
        // 获取最新结果
        PrizeResultDTO prizeResultDTO = new PrizeResultDTO();
        List<String> resultList = getSsqResult(prizeResultDTO);
        // 客户端输入
        List<String> myList = new ArrayList<>(Arrays.asList(number.split(",")));

        if (myList.size() != 7) {
            throw new Exception("参数不合法!");
        }

        List<String> myFrontList = new ArrayList<>(myList.subList(0, 6));
        List<String> myAfterList = new ArrayList<>(myList.subList(6, 7));

        System.out.println("my前: " + JSONArray.toJSONString(myFrontList));
        System.out.println("my后: " + JSONArray.toJSONString(myAfterList));
        List<String> resultFrontList = new ArrayList<>(resultList.subList(0, 6));
        List<String> resultAfterList = new ArrayList<>(resultList.subList(6, 7));

        System.out.println("result前: " + JSONArray.toJSONString(resultFrontList));
        System.out.println("result后: " + JSONArray.toJSONString(resultAfterList));

        myFrontList.retainAll(resultFrontList);
        myAfterList.retainAll(resultAfterList);

        System.out.println(myFrontList.size() + ": " + JSONArray.toJSONString(myFrontList));
        System.out.println(myAfterList.size() + ": " + JSONArray.toJSONString(myAfterList));
        String rule = String.format("%s+%s", myFrontList.size(), myAfterList.size());

        prizeResultDTO.setLotteryRes(StringUtils.join(resultList, ","));
        prizeResultDTO.setPrize(rule);
        prizeResultDTO.setPrizeAmount(SsqRuleEnum.getPrizeNameByRule(rule));
        prizeResultDTO.setMyPrize("前区: " + StringUtils.join(myFrontList, ",") + "后区: " + StringUtils.join(myAfterList, ","));
        log.info("prizeResultDTO: {}", JSONObject.toJSONString(prizeResultDTO));
        return prizeResultDTO;
    }

    private static List<String> getSsqResult(PrizeResultDTO prizeResultDTO) throws IOException {
        String url = "http://apis.juhe.cn/lottery/query?lottery_id=ssq&lottery_no=&key=380edb27d1f6d76c2a4ab3504def40a8";
        String result = HttpClientUtils.httpGet(url, HttpClientUtils.CHARSET_UTF8);
        log.info("result: {}", result);
        JSONObject resultJson = JSONObject.parseObject(result);
        String number = resultJson.getJSONObject("result").getString("lottery_res");
        log.info("number: {}", number);
        prizeResultDTO.setPeriods(StringUtils.emptyIfNull(resultJson.getJSONObject("result").get("lottery_no")));
        prizeResultDTO.setLotteryPoolAmount(StringUtils.emptyIfNull(resultJson.getJSONObject("result").get("lottery_pool_amount")));
        prizeResultDTO.setOpenDate(StringUtils.emptyIfNull(resultJson.getJSONObject("result").get("lottery_date")));
        return new ArrayList<>(Arrays.asList(number.split(",")));
    }

    private static List<String> getDltResult(PrizeResultDTO prizeResultDTO) throws IOException {
        String url = "http://apis.juhe.cn/lottery/query?lottery_id=dlt&lottery_no=&key=380edb27d1f6d76c2a4ab3504def40a8";
        String result = HttpClientUtils.httpGet(url, HttpClientUtils.CHARSET_UTF8);
        log.info("result: {}", result);
        JSONObject resultJson = JSONObject.parseObject(result);
        String number = resultJson.getJSONObject("result").getString("lottery_res");
        log.info("number: {}", number);
        prizeResultDTO.setPeriods(StringUtils.emptyIfNull(resultJson.getJSONObject("result").get("lottery_no")));
        prizeResultDTO.setLotteryPoolAmount(StringUtils.emptyIfNull(resultJson.getJSONObject("result").get("lottery_pool_amount")));
        prizeResultDTO.setOpenDate(StringUtils.emptyIfNull(resultJson.getJSONObject("result").get("lottery_date")));
        return new ArrayList<>(Arrays.asList(number.split(",")));
    }

    @Data
    private static class PrizeResultDTO {
        private String lotteryRes;
        private String prize;
        private String prizeRequire;
        private String prizeAmount;
        private String myPrize;
        /**
         * 期数
         */
        private String periods;
        /**
         * 奖池奖金
         */
        private String lotteryPoolAmount;
        /**
         * 开奖日期
         */
        private String openDate;
    }

}